package com.toocms.tab.network.encrypt;

import com.blankj.utilcode.util.CollectionUtils;
import com.blankj.utilcode.util.EncodeUtils;
import com.blankj.utilcode.util.EncryptUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.StringUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.toocms.tab.TooCMSApplication;

import java.io.IOException;
import java.util.List;

import okhttp3.RequestBody;
import rxhttp.wrapper.annotation.Param;
import rxhttp.wrapper.entity.KeyValuePair;
import rxhttp.wrapper.param.FormParam;
import rxhttp.wrapper.param.Method;

/**
 * @Description:
 * @Author: Zero
 * @CreateDate: 2023/4/10 15:15
 */
@Param(methodName = "postEncryptForm")
public class PostEncryptFormParam extends FormParam {

    public PostEncryptFormParam(String url) {
        super(url, Method.POST);
    }

    @Override
    public RequestBody getRequestBody() {
        // 加密配置，配置为空则不加密
        ApiEncryptOption option = TooCMSApplication.getInstance().getAppConfig().getApiEncryptOption();
        if (option == null) return super.getRequestBody();
        // 所有body参数，参数为则不加密
        List<KeyValuePair> bodyParam = getBodyParam();
        if (bodyParam == null) return super.getRequestBody();
        // 如果带文件则不加密
        if (isMultipart()) return super.getRequestBody();
        Gson gson = new GsonBuilder().registerTypeAdapter(bodyParam.getClass(), typeAdapter).create();
        // RSA加密
        String json = GsonUtils.toJson(gson, bodyParam);
        if (option.isOutputRealParam()) LogUtils.e(json);
        byte[] publicKey = option.getPublicKey().getBytes();
        int keySize = option.getKeySize();
        String transformation = option.getTransformation();
        String encryptStr = EncodeUtils.base64Encode2String(
                EncryptUtils.encryptRSA(
                        json.getBytes(),
                        EncodeUtils.base64Decode(publicKey),
                        keySize == 0 ? publicKey.length : keySize,
                        StringUtils.isEmpty(transformation) ? "RSA/None/PKCS1Padding" : transformation));
        removeAllBody();
        String paramName = option.getParamName();
        if (option.isAddHeader()) {
            addHeader(paramName, encryptStr);
        } else {
            add(paramName, encryptStr);
        }
        return super.getRequestBody();
    }

    private final TypeAdapter<List<KeyValuePair>> typeAdapter = new TypeAdapter<>() {
        @Override
        public void write(JsonWriter out, List<KeyValuePair> value) throws IOException {
            out.beginObject();
            CollectionUtils.forAllDo(value, (index, item) -> {
                try {
                    out.name(item.getKey()).value(item.getValue().toString());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            out.endObject();
            out.flush();
        }

        @Override
        public List<KeyValuePair> read(JsonReader in) throws IOException {
            return null;
        }
    };
}
